﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.IO;
using Microsoft.Xna.Framework.Media;

namespace FierceWar
{
	public class BuildMapScreen : Screen
	{
		#region Fields.
		protected BoundingBoxTree BBT;

		protected List<ElementalModel> Models = new List<ElementalModel>();
		private ElementalModel _activeElementalModel;
		private Vector3 _tempPosition;

		protected List<ElementalModel> Roads = new List<ElementalModel>();

		private ModelType[] _animals;
		private ModelType[] _arms;
		private ModelType[] _barrels;
		private ModelType[] _cars;
		private ModelType[] _fences;
		private ModelType[] _houses;
		private ModelType[] _natures;
		private ModelType[] _others;
		private ModelType[] _activeGroup;
		private ModelType[] _preload;
		private int _currentIndexOfActiveGroup;

		private Camera _camera;

		private bool _holdEnable = false;

		public string MapName;
		public bool IsSaved = true;
		#endregion

		public BuildMapScreen(GameResources resources, List<EventHandler> screenEvents)
			: base(resources, screenEvents)
		{
			LoadContent();
			LoadPreContent();
		}

		public void LoadContent()
		{
			// Restore to the initial statement.
			Reset();

			#region Setup model-type groups.
			// Setup model-type groups.
			_animals = new ModelType[] {
						 ModelType.Dog,
						 ModelType.Horse,
			};
			_arms = new ModelType[] {
						 ModelType.Bradley,
						 ModelType.EuroFighter,
						 ModelType.Helicopter,
						 ModelType.Mig_35,
						 ModelType.Harpoon,
						 ModelType.Shockwave,
                         ModelType.Bullet,
                         ModelType.Ship1,
                         ModelType.Ship2,
                         ModelType.Ship3,
                         ModelType.Ship4,
                         ModelType.Ship5,
                         ModelType.Ship6,
                         ModelType.Ship7,
                         ModelType.Ship8,
                         ModelType.Ship9,
			};
			_barrels = new ModelType[] {
						 ModelType.Barrel1,
						 ModelType.Barrel2,
						 ModelType.Barrel3,
						 ModelType.Barrel4,
						 ModelType.Barrel5,
						 ModelType.Barrel6,
						 ModelType.Barrel7,
						 ModelType.Barrel8,
						 ModelType.Barrel9,
						 ModelType.Barrel10,
						 ModelType.Crate,
			};
			_cars = new ModelType[] {
						 ModelType.Buggy,
						 ModelType.Carriage,
			};
			_fences = new ModelType[] {
						 ModelType.Fence,
						 ModelType.Wall1_Full,
						 ModelType.Wall1_Middle,
						 ModelType.Wall1_OneSide,
						 ModelType.Wall1_Standard,
						 ModelType.Wall2_Full,
						 ModelType.Wall2_Middle,
						 ModelType.Wall2_OneSide,
						 ModelType.Wall2_Standard,
						 ModelType.Wall3_Full,
						 ModelType.Wall3_OneSide,
						 ModelType.Wall3_Standard,
						 ModelType.Wall4,
						 ModelType.Wall5,
						 ModelType.Wall6,
			};
			_houses = new ModelType[] {
						 ModelType.House1,
						 ModelType.House2,
						 ModelType.House3,
						 ModelType.House4,
						 ModelType.House5,
						 ModelType.House6,
						 ModelType.House7,
						 ModelType.House8,
						 ModelType.House9,
						 ModelType.Tower,
			};
			_natures = new ModelType[] {
						 ModelType.Grass,
						 ModelType.Tree1_Green,
						 ModelType.Tree1_White,
						 ModelType.Tree2_Black,
						 ModelType.Tree2_Green,
						 ModelType.Stone_Normal,
						 ModelType.Stone_Special,
			};
			_others = new ModelType[] {
						 ModelType.Banner,
						 ModelType.Skeleton,
						 ModelType.StreetSign,
			};
			_preload = new ModelType[] {
						 ModelType.Bullet,
						 ModelType.House2,
						 ModelType.House4,
						 ModelType.Shockwave,
						 ModelType.StreetSign,
			};
			#endregion
		}

		public void LoadPreContent()
		{
			for (int i = 0; i < _preload.Length; i++)
			{
				new ElementalModel(Resources.Content, _preload[i]);
			}
		}

		public override void Reset()
		{
			base.Reset();

			// Setup camera.
			_camera = new MyCamera(Vector3.Zero, 0.0f, -MathHelper.PiOver4,
				Resources.GraphicsDevice);
			((MyCamera)_camera).Reset();

			Models.Clear();
			Roads.Clear();
			_activeElementalModel = null;
			_holdEnable = false;

			// Draw ground first.
			Models.Add(new ElementalModel(Resources.Content, ModelType.Ground));

			MapName = null;
			IsSaved = true;

			// Create BoundingBoxTree.
			BBT = new BoundingBoxTree(
				new Vector3(-65536.0f, 0.0f, -65536.0f),
				new Vector3(65536.0f, 131072.0f, 65536.0f));

			StopMusic();
		}

		public override void Update(GameTime gameTime)
		{
			base.Update(gameTime);

			// Pause.
			if (KeyboardInput.IsKeyPressed(Keys.P))
			{
				ScreenEvents[0].Invoke(this, new EventArgs());
			}

			// Show help.
			if (KeyboardInput.IsKeyPressed(Keys.H))
			{
				ScreenEvents[4].Invoke(this, new EventArgs());
			}

			// Save map.
			if (KeyboardInput.IsKeyDown(Keys.LeftControl) &&
				KeyboardInput.IsKeyPressed(Keys.S))
			{
				if (KeyboardInput.IsKeyDown(Keys.LeftShift))
				{
					// Save as.
					ScreenEvents[3].Invoke(this, new EventArgs());
				}
				else
				{
					if (MapName == null)
					{
						// First save.
						ScreenEvents[2].Invoke(this, new EventArgs());
					}
					else
					{
						// Next save.
						SaveMap(MapName);
						IsSaved = true;
					}
				}
			}

			// Clear all.
			if (KeyboardInput.IsKeyDown(Keys.LeftControl) &&
				KeyboardInput.IsKeyPressed(Keys.N))
			{
				Reset();
			}

			// Update Camera.
			UpdateCamera(gameTime);

			// Build map using models.
			HandleInputOnModel(); 
		}

		public override void Draw(GameTime gameTime)
		{
			base.Draw(gameTime);

			Resources.GraphicsDevice.BlendState = BlendState.Opaque;
			Resources.GraphicsDevice.DepthStencilState = DepthStencilState.None;
			Resources.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
			Resources.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

			// Draw the ground.
			Models[0].Draw(_camera.View, _camera.Projection, ((MyCamera)_camera).Position);

			// Draw road.
			foreach (ElementalModel road in Roads)
			{
				road.Draw(_camera.View, _camera.Projection, ((MyCamera)_camera).Position);
			}

			// Draw other models.
			Resources.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
			for (int i = 1; i < Models.Count; i++)
			{
				Models[i].Draw(_camera.View, _camera.Projection, ((MyCamera)_camera).Position);
			}
		}

		public override void PlayMusic()
		{
			base.PlayMusic();
			MediaPlayer.Play(Resources.BuildMapBackground);
		}

		#region Methods.
		#region Handle models.
		private void HandleInputOnModel()
		{
			#region Keyboard Input: load models, cancel, delete, rotate, scale.

			#region Cancel move.
			if (KeyboardInput.IsKeyPressed(Keys.Escape))
			{
				if (!_holdEnable || (_activeElementalModel == null) ||
					!_activeElementalModel.IsPlaced)
				{
					// Show menu.
					ScreenEvents[1].Invoke(this, new EventArgs());
				}
				else
				{
					_activeElementalModel.Position = _tempPosition;
					_activeElementalModel = null;
					_holdEnable = false;
				}
			}
			#endregion

			#region Load models.
			if (KeyboardInput.IsKeyPressed(Keys.D1))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_houses, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(1);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D2))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_fences, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(2);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D3))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_natures, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(3);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D4))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_barrels, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(4);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D5))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_arms, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(5);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D6))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_cars, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(6);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D7))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_animals, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(7);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D8))
			{
				if (!_holdEnable)
				{
					LoadElementalModelInGroup(_others, true);
				}
				else
				{
					LoadElementalModelInActiveGroup(8);
				}
			}

			if (KeyboardInput.IsKeyPressed(Keys.D9))
			{
				LoadElementalModelInActiveGroup(9);
			}

			if (KeyboardInput.IsKeyPressed(Keys.D0))
			{
				LoadElementalModelInActiveGroup(10);
			}

			if (KeyboardInput.IsKeyPressed(Keys.F1))
			{
				LoadElementalModelInGroup(_activeGroup, false);
			}
			
			if (KeyboardInput.IsKeyPressed(Keys.F2))
			{
				LoadElementalModelInGroup(_activeGroup, true);
			}
			#endregion

			#region Delete.
			if (KeyboardInput.IsKeyPressed(Keys.Delete) && _holdEnable)
			{
				BBT.Remove(_activeElementalModel);
				Models.Remove(_activeElementalModel);
				_activeElementalModel = null;
				_holdEnable = false;
				_activeGroup = null;
				_currentIndexOfActiveGroup = -1;
				Resources.BuildingDestruction.Play();
			}
			#endregion

			#region Rotate.
			if (KeyboardInput.IsKeyPressed(Keys.Tab) && _holdEnable)
			{
				float rotationAmount = 10.0f;
				if (KeyboardInput.IsKeyDown(Keys.Space))
				{
					rotationAmount = 1.0f;
				}

				if (KeyboardInput.IsKeyDown(Keys.LeftShift))
				{
					_activeElementalModel.Rotation.Y +=
						MathHelper.ToRadians(rotationAmount);
				}
				else
				{
					_activeElementalModel.Rotation.Y -=
						MathHelper.ToRadians(rotationAmount);
				}
			}
			#endregion
			#endregion

			#region Mouse Input: Move models.
			// Pick a given model.
			if (MouseInput.IsRightPress && MouseInput.IsOnScreen)
			{
				ElementalModel model = GetPickedElementalModel(Models);
				if (model != null)
				{
					_holdEnable = true;
					_activeElementalModel = model;
					_tempPosition = _activeElementalModel.Position;
				}
			}

			// Set new position.
			if ((MouseInput.IsLeftPress || KeyboardInput.IsKeyPressed(Keys.Enter)) &&
				(_activeElementalModel != null) && MouseInput.IsOnScreen)
			{
				if (BBT.HasCollisionForBuildingMap(_activeElementalModel))
				{
					_activeElementalModel.EnablePlaced = false;
					if (KeyboardInput.IsKeyDown(Keys.Space))
					{
						_activeElementalModel.EnablePlaced = true;
					}
				}
				else
				{
					_activeElementalModel.EnablePlaced = true;
				}

				if (_activeElementalModel.EnablePlaced)
				{
					_activeElementalModel.IsPlaced = true;
					BBT.Remove(_activeElementalModel);
					BBT.InsertForBuildingMap(_activeElementalModel);
					Resources.BuildingPlacement.Play();
					IsSaved = false;
					if (KeyboardInput.IsKeyDown(Keys.LeftAlt))
					{
						ElementalModel tmpModel = new ElementalModel(
							Resources.Content, _activeElementalModel.Type);
						tmpModel.Scale = _activeElementalModel.Scale;
						tmpModel.Rotation = _activeElementalModel.Rotation;
						_activeElementalModel = tmpModel;
						Models.Add(_activeElementalModel);
					}
					else
					{
						_holdEnable = false;
						_activeElementalModel = null;
						_activeGroup = null;
						_currentIndexOfActiveGroup = -1;
					}		 
				}		
			}

			// Create road of map.
			if (MouseInput.IsLeftPress && !_holdEnable)
			{
				if (KeyboardInput.IsKeyDown(Keys.F))
				{
					Vector3 position = RoundPosition(
						MouseToWorld(_camera.View, _camera.Projection), 800, 800);
					if (!IsRoadModelAt(position))
					{
						ElementalModel road = new ElementalModel(Resources.Content, ModelType.Road);
						road.Position = position;
						road.Scale = new Vector3(4.0f, 0.000001f, 4.0f);
						Roads.Add(road);
					}

					IsSaved = false;
				}
				else if (KeyboardInput.IsKeyDown(Keys.G))
				{
					Roads.Remove(GetPickedElementalModel(Roads));
					IsSaved = false;
				}
			}
			#endregion

			#region Handle while model is moving.
			if (_holdEnable)
			{
				if (KeyboardInput.IsKeyDown(Keys.LeftControl))
				{
					_activeElementalModel.Position =
						MouseToWorld(_camera.View, _camera.Projection);
				}
				else
				{
					_activeElementalModel.Position = RoundPosition(
						MouseToWorld(_camera.View, _camera.Projection),
						200, 200);
				}
			}
			#endregion
		}

		private bool IsRoadModelAt(Vector3 position)
		{
			foreach (ElementalModel road in Roads)
			{
				if (road.Position == position)
				{
					return true;
				}
			}
			return false;
		}

		public void LoadElementalModel(ModelType modelType)
		{
			LoadElementalModelWithMode(modelType, false);
		}

		public void LoadElementalModelWithMode(ModelType modelType, bool overload)
		{
			if (!_holdEnable || overload)
			{
				Models.Remove(_activeElementalModel);
				_activeElementalModel = new ElementalModel(Resources.Content, modelType);
				Models.Add(_activeElementalModel);
				_holdEnable = true;
			}
		}

		public void LoadElementalModelInGroup(ModelType[] group, bool isAscending)
		{
			if (group == null)
			{
				return;
			}

			if (_activeGroup == null)
			{
				if (!_holdEnable)
				{
					_activeGroup = group;
					_currentIndexOfActiveGroup = -1;
				}
				else
				{
					return;
				}
			}
			else if (_activeGroup != group)
			{
				return;
			}

			if (!isAscending)
			{
				_currentIndexOfActiveGroup--;
				if (_currentIndexOfActiveGroup < 0)
				{
					_currentIndexOfActiveGroup = _activeGroup.Length - 1;
				}
			}
			else
			{
				_currentIndexOfActiveGroup++;
				if (_currentIndexOfActiveGroup == _activeGroup.Length)
				{
					_currentIndexOfActiveGroup = 0;
				}
			}

			LoadElementalModelWithMode(_activeGroup[_currentIndexOfActiveGroup], true);
		}

		public void LoadElementalModelInActiveGroup(int index)
		{
			if (_activeGroup == null)
			{
				return;
			}

			if ((index < 1) || (index > _activeGroup.Length))
			{
				return;
			}

			_currentIndexOfActiveGroup = index - 1;
			LoadElementalModelWithMode(_activeGroup[_currentIndexOfActiveGroup], true);
		}

		private ElementalModel GetPickedElementalModel(List<ElementalModel> models)
		{
			ElementalModel result = null;
			float minDistance = -1.0f;
			foreach (ElementalModel model in models)
			{
				if ((model.Type != ModelType.Ground) &&
					(model.BoundingBox.Intersects(
						MouseToRay(_camera.View, _camera.Projection)) != null))
				{
					if (minDistance < 0.0f)
					{
						minDistance = Vector3.Distance(
							ProjectedVector(((MyCamera)_camera).Position),
							model.Position);
						result = model;
					}
					else
					{
						float distance = Vector3.Distance(
							ProjectedVector(((MyCamera)_camera).Position),
							model.Position);
						if (distance < minDistance)
						{
							minDistance = distance;
							result = model;
						}
					}
				}
			}
			return result;
		}

		private Vector3 ProjectedVector(Vector3 position)
		{
			return new Vector3(position.X, 0.0f, position.Z);
		}
		#endregion

		#region Convert the mouse 2D position vector into 3D vector on the world space.
		private Vector3 PositionOnScreenToWorld(Vector2 position,
			Matrix view, Matrix projection)
		{
			Vector3 nearSource = new Vector3(position, 0.0f);
			Vector3 farSource = new Vector3(position, 1.0f);

			Vector3 nearPoint = Resources.GraphicsDevice.Viewport.Unproject(
				nearSource, projection, view, Matrix.Identity);
			Vector3 farPoint = Resources.GraphicsDevice.Viewport.Unproject(
				farSource, projection, view, Matrix.Identity);

			Vector3 direction = farPoint - nearPoint;
			direction.Normalize();

			Ray r = new Ray(nearPoint, direction);
			Plane p = new Plane(Vector3.Up, 0f);

			float denominator = Vector3.Dot(p.Normal, r.Direction);
			float numerator = Vector3.Dot(p.Normal, r.Position) + p.D;
			float t = -(numerator / denominator);

			return (nearPoint + direction * t);
		}

		private Vector3 MouseToWorld(Matrix view, Matrix projection)
		{
			return PositionOnScreenToWorld(MouseInput.Position, view, projection);
		}

		private Ray PositionOnScreenToRay(Vector2 position, Matrix view,
			Matrix projection)
		{
			Vector3 nearSource = new Vector3(position, 0.0f);
			Vector3 farSource = new Vector3(position, 1.0f);

			Vector3 nearPoint = Resources.GraphicsDevice.Viewport.Unproject(
				nearSource, projection, view, Matrix.Identity);
			Vector3 farPoint = Resources.GraphicsDevice.Viewport.Unproject(
				farSource, projection, view, Matrix.Identity);

			Vector3 direction = farPoint - nearPoint;
			direction.Normalize();

			return new Ray(nearPoint, direction);
		}

		private Ray MouseToRay(Matrix view, Matrix projection)
		{
			return PositionOnScreenToRay(MouseInput.Position, view, projection);
		}
		#endregion

		#region Round number and round 3D position vector.
		private Vector3 RoundPosition(Vector3 position, int xRange, int zRange)
		{
			return new Vector3(RoundDomain(position.X, xRange), position.Y,
				RoundDomain(position.Z, zRange));
		}

		private float RoundDomain(double number, int range)
		{
			int kth = ((int)number) / range;
			return (kth * range);
		}
		#endregion

		#region Save map to file.
		public void SaveMap(string fileName)
		{
			System.IO.Directory.CreateDirectory("Map");
			FileInfo file = new FileInfo("Map/" + fileName);
			StreamWriter sw = file.CreateText();
			SaveObjectsToFile(Models, sw, true);
			SaveObjectsToFile(Roads, sw, false);
			sw.Close();
		}

		private void SaveObjectsToFile(List<ElementalModel> objects,
			StreamWriter sw, bool saveBoundingBoxMasterIndexes)
		{
			foreach (ElementalModel model in objects)
			{
				StringBuilder sb = new StringBuilder();

				// save model's type.
				int type = (int)model.Type;
				sb.Append(type);
				sb.Append(" ");
				sw.Write(sb.ToString());

				// save model's position.
				sb.Clear();
				sb.Append(model.Position.X);
				sb.Append(" ");
				sb.Append(model.Position.Y);
				sb.Append(" ");
				sb.Append(model.Position.Z);
				sb.Append(" ");
				sw.Write(sb.ToString());

				// save model's scale vector.
				sb.Clear();
				sb.Append(model.Scale.X);
				sb.Append(" ");
				sb.Append(model.Scale.Y);
				sb.Append(" ");
				sb.Append(model.Scale.Z);
				sb.Append(" ");
				sw.Write(sb.ToString());

				// save model's rotation vector.
				sb.Clear();
				sb.Append(model.Rotation.X);
				sb.Append(" ");
				sb.Append(model.Rotation.Y);
				sb.Append(" ");
				sb.Append(model.Rotation.Z);
				sb.Append(" ");
				sw.Write(sb.ToString());

				// save BBMI.
				if (saveBoundingBoxMasterIndexes)
				{
					foreach (int index in model.BoundingBoxMasterIndexes)
					{
						sb.Clear();
						sb.Append(index);
						sb.Append(" ");
						sw.Write(sb.ToString());
					}
				}

				sw.WriteLine();
			}
		}
		#endregion

		void UpdateCamera(GameTime gameTime)
		{
			if (MouseInput.LastScrollWheelValue != MouseInput.CurrentScrollWheelValue)
			{
				float pitch = MouseInput.CurrentScrollWheelValue -
					MouseInput.LastScrollWheelValue;
				// Rotate the camera
				((MyCamera)_camera).Rotate(pitch * 0.001f);
			}

			Vector3 translation = Vector3.Zero;
			Vector3 translationOnPlane = Vector3.Zero;
			float sideRotationAmount = 0.0f;

			// Determine in which direction to move the camera
			if (KeyboardInput.IsKeyDown(Keys.W))
			{
				translationOnPlane += Vector3.Forward * 60;
			}

			if (KeyboardInput.IsKeyDown(Keys.S) &&
				!KeyboardInput.IsKeyDown(Keys.LeftControl))
			{
				translationOnPlane += Vector3.Backward * 60;
			}

			if (KeyboardInput.IsKeyDown(Keys.Up))
			{
				if (KeyboardInput.IsKeyDown(Keys.LeftShift))
				{
					translation += Vector3.Forward * 60;
				}
				else
				{
					translation += Vector3.Forward * 10;
				}
			}

			if (KeyboardInput.IsKeyDown(Keys.Down))
			{
				if (KeyboardInput.IsKeyDown(Keys.LeftShift))
				{
					translation += Vector3.Backward * 60;
				}
				else
				{
					translation += Vector3.Backward * 10;
				}
			}

			if (KeyboardInput.IsKeyDown(Keys.A))
			{
				translation += Vector3.Left * 10;
			}

			if (KeyboardInput.IsKeyDown(Keys.D))
			{
				translation += Vector3.Right * 10;
			}

			if (KeyboardInput.IsKeyDown(Keys.PageUp))
			{
				translationOnPlane += Vector3.Forward * 200.0f;
			}

			if (KeyboardInput.IsKeyDown(Keys.PageDown))
			{
				translationOnPlane += Vector3.Backward * 200.0f;
			}

			if (KeyboardInput.IsKeyDown(Keys.Home))
			{
				translationOnPlane += Vector3.Left * 200.0f;
			}

			if (KeyboardInput.IsKeyDown(Keys.End))
			{
				translationOnPlane += Vector3.Right * 200.0f;
			}

			if (KeyboardInput.IsKeyDown(Keys.Q))
			{
				sideRotationAmount += 0.01f;
			}

			if (KeyboardInput.IsKeyDown(Keys.E))
			{
				sideRotationAmount -= 0.01f;
			}

			if (KeyboardInput.IsKeyDown(Keys.R))
			{
				((MyCamera)_camera).Reset();
			}

			if (KeyboardInput.IsKeyPressed(Keys.Left))
			{
				sideRotationAmount += MathHelper.ToRadians(45.0f);
			}

			if (KeyboardInput.IsKeyPressed(Keys.Right))
			{
				sideRotationAmount -= MathHelper.ToRadians(45.0f);
			}

			// Move 4 units per millisecond, independent of frame rate
			translation *= 0.5f *
				(float)gameTime.ElapsedGameTime.TotalMilliseconds;

			// Move the camera
			((MyCamera)_camera).Move(translation);
			((MyCamera)_camera).MoveOnPlane(translationOnPlane);
			((MyCamera)_camera).Rotate(sideRotationAmount, 0.0f);

			// Update the camera
			_camera.Update();
		}
		#endregion
	}
}
